from rest_framework import serializers
from .models import BookInfo, HeroInfo


class BookInfoSerializers(serializers.ModelSerializer):
    # 书籍序列化器,也可以在模型类里定义序列化器
    class Meta:
        # model 指明关联的模型类,参照哪个模型类
        model = BookInfo
        fields = '__all__'
        extra_kwargs = {
            'id': {
                'help_text': '阅读量'
            }
        }

        # exclude可以明确排除掉哪些字段
        # exclude = ('image',)

        # 指明响应(显示)的字段
        # fields = ['id', 'bpub_date', 'btitle']

        # read_only_fields指明只读字段，即仅用于序列化输出的字段
        # read_only_fields = ('id', 'bread', 'bcomment')

        # extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
        # extra_kwargs = {
        #     'bread': {'min_value': 0, 'required': True},
        #     'bcomment': {'min_value': 0, 'required': True},
        # }

        # __all__表名包含所有字段
        # fields = '__all__'


class BookInfoModelSerializer2(serializers.ModelSerializer):
    class Meta:
        model = BookInfo
        fields = ['id', 'btitle']


class HeroInfoSerializers(serializers.ModelSerializer):
    class Meta:
        model = HeroInfo
        fields = '__all__'
        # TODO
        depth = 1


class BookInfoSerializer(serializers.Serializer):
    """图书数据序列化器"""
    """
    序列化器的使用：
    在工程目录下进行终端操作：
    获取单条序列化数据
    1.python manage.py shell
    2.from booktest.models import BookInfo
    3.from booktest.serializers import BookInfoSerializer
    4.book = BookInfo.objects.get(id=1)
    5.ser = BookInfoSerializer(book)
    6.ser.data
    
    获取多条序列化数据的查询集QuerySet
    1.python manage.py shell
    2.from booktest.models import BookInfo
    3.from booktest.serializers import BookInfoSerializer
    4.book = BookInfo.objects.all()
    5.ser = BookInfoSerializer(book,many = True) 
    6.ser.data
    """
    id = serializers.IntegerField(label='ID', read_only=True)
    btitle = serializers.CharField(label='名称', max_length=20)
    bpub_date = serializers.DateField(label='发布日期', required=False)
    bread = serializers.IntegerField(label='阅读量', required=False)
    bcomment = serializers.IntegerField(label='评论量', required=False)
    image = serializers.ImageField(label='图片', required=False)
    extra_kwargs = {
        'id': {
            'help_text': '阅读量'
        }
    }

    # 获取单条序列化数据,执行上述操作
    # 关联多个对象数据，使用many=True参数
    # {'image': None, 'heroinfo_set': [1, 2, 3, 4, 5],
    #  'bread': 12, 'bpub_date': '1980-05-01', 'btitle': '射雕英雄传', 'id': 1, 'bcomment': 34}
    # heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True,many=True)

    # 每次操作需要重新打开shell,否则不会更新结果
    # {'heroinfo_set': 'booktest.HeroInfo.None', 'btitle': '射雕英雄传',
    #  'id': 1, 'image': None, 'bpub_date': '1980-05-01', 'bcomment': 34, 'bread': 12}
    # heroinfo_set = serializers.StringRelatedField()

    # {'image': None, 'bcomment': 34, 'heroinfo_set': ['郭靖', '黄蓉', '黄药师', '欧阳锋', '梅超风'],
    # 'bpub_date': '1980-05-01', 'id': 1, 'bread': 12, 'btitl
    heroinfo_set = serializers.StringRelatedField(many=True)

    # 自定义验证行为
    # 单个字段验证
    def validate_btitle(self, value):
        if 'django' not in value.lower():
            raise serializers.ValidationError('django 不在书名中')
        # django 在书名里
        return value

    # 多个字段比较验证
    def validate(self, attrs):
        bread = attrs['bread']
        bcomment = attrs['bcomment']
        if bread < bcomment:
            raise serializers.ValidationError('阅读量小于评论量')
        return attrs

    # 创建数据
    def create(self, validated_data):
        return BookInfo.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.btitle = validated_data.get('btitle', instance.btitle)
        instance.bpub_date = validated_data.get('bpub_date', instance.bpub_date)
        instance.bread = validated_data.get('bread', instance.bread)
        instance.bcomment = validated_data.get('bcomment', instance.bcomment)
        instance.save()
        return instance


class HeroInfoSerializer(serializers.Serializer):
    """英雄数据序列化器"""
    """
    >>> from booktest.serializers import HeroInfoSerializer
    >>> from booktest.models import HeroInfo
    >>> hero = HeroInfo.objects.get(id=6)
    >>> serializer = HeroInfoSerializer(hero)
    >>> serializer.data
    {'hbook': 2, 'hname': '乔峰', 'hcomment': '降龙十八掌', 'hgender': 1, 'id': 6}
    """
    GENDER_CHOICES = (
        (0, 'male'),
        (1, 'female')
    )
    id = serializers.IntegerField(label='ID', read_only=True)
    hname = serializers.CharField(label='名字', max_length=20)
    hgender = serializers.ChoiceField(choices=GENDER_CHOICES, label='性别', required=False)
    hcomment = serializers.CharField(label='描述信息', max_length=200, required=False, allow_null=True)
    # 外键
    # 每次操作需要重新打开shell,否则不会更新结果

    # PrimaryKeyRelatedField 此字段将被序列化为关联对象的主键
    # hbook = serializers.PrimaryKeyRelatedField(read_only=True, label='书名')

    # StringRelatedField 此字段将被序列化为关联对象的字符串表示方式（即__str__方法的返回值）
    # hbook = serializers.StringRelatedField(label='书名')

    # 此字段将被序列化为获取关联对象数据的接口链接
    # 在urls.py 中定义
    #  url(r'books/(?P<pk>\d+)/$', views.HeroInfoDetail.as_view(), name='books-detail')
    # hbook = serializers.HyperlinkedRelatedField(label='图书', read_only=True, view_name='books-detail')

    # 使用关联对象的序列化器
    hbook = BookInfoSerializer()